﻿using adb;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using System.Linq;
using Z.EntityFramework.Plus;
using Masuit.Tools.Security;
using System.Collections.Generic;
using PowerStation.RequestModel;
using Microsoft.EntityFrameworkCore;
using adb.excel;
using System.IO;
using Masuit.Tools;
using Microsoft.Net.Http.Headers;
using System;
using PowerStation.TableModel;
using Microsoft.AspNetCore.Authorization;
using NStandard;

namespace PowerStation.Controllers
{
    /// <summary>
    /// 报表管理
    /// </summary>
    public class WorkTableController : BaseApi<WorkTableController>
    {
        /// <summary>
        /// 报表管理
        /// </summary>
        /// <param name="content"></param>
        public WorkTableController(IHttpContextAccessor content) : base(content)
        {
        }


        /// <summary>
        /// 填写日限购量
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<bool>> Create(List<RequestLimitDataModel> model)
        {
            //var powerStationIds = model.Select(x => x.powerStationId).Distinct();
            //if (powerStationIds.Count() > 1) return ResultApi.error(false, "数据中有多个电站数据,请分开导入");
            //await this.IsCheckPowerStation(powerStationIds.First());

            using (var tran = await this._deviceDB.Database.BeginTransactionAsync())
            {




                foreach (var item in model)
                {
                    await this._deviceDB.tLimitPowerData.Where(x => EF.Functions.DateDiffDay(x.addTime, item.date) == 0 && item.powerStationId == item.powerStationId).DeleteAsync();
                }
                await this._deviceDB.SaveChangesAsync();
                var list = model.Select(x =>
                {
                    var mmm = new tLimitPowerData
                    {
                        addTime = x.date,
                        limitPowerValue = x.limitPowerValue,
                        limitPower_powerStationId_fk = x.powerStationId
                    };
                    return mmm;
                }).ToList();
                await this._deviceDB.tLimitPowerData.AddRangeAsync(list);

                await this._deviceDB.SaveChangesAsync();
                var ok = true;
                foreach (var item in list)
                {
                    ok = ok && await UpdateData(item);
                }
                if (ok)
                {
                    await tran.CommitAsync();
                }
                return ResultApi.okOrError<bool>(ok, ok);
            }
        }
        /// <summary>
        /// 更新统计数据
        /// </summary>
        /// <param name="m">计划数据</param>
        /// <returns></returns>
        private async Task<bool> UpdateData(tLimitPowerData m)
        {
            try
            {
                var dateTime = new DateTime(m.addTime.Value.Year, m.addTime.Value.Month, m.addTime.Value.Day);
                var oldData = await this._deviceDB.tStatisticsData.FirstOrDefaultAsync(x => x.statisticsDataDate == dateTime && x.statisticsStation_powerStationId_fk == m.limitPower_powerStationId_fk && x.deviceGroup == "1#");
                if (oldData != null)
                {
                    oldData.limitPower = m.limitPowerValue * 10000;
                }
                else
                {
                    await this._deviceDB.AddAsync(new tStatisticsData
                    {
                        statisticsDataDate = dateTime,
                        statisticsStation_powerStationId_fk = m.limitPower_powerStationId_fk,
                        deviceGroup = "1#",
                        limitPower = m.limitPowerValue * 10000
                    });
                }
                await this._deviceDB.SaveChangesAsync();
                return true;

            }
            catch (Exception ex)
            {
                Console.WriteLine($"更新统计数据出错:{ex.Message}");
                return false;

            }
        }
        /// <summary>
        /// 限购电量数据导入
        /// </summary>
        [HttpPost]
        public async Task<ResultApi<bool>> LimiDataInput([FromForm] RequestLimitDataInputModel model)
        {
            if (model.xlsFile.Length > 0)
            {
                var titles = await this._db.tExcelTitle.Where(x => x.excelType == 10).ToListAsync();
                if (titles.Count > 0)
                {

                    Task<List<LimitInputModel>> task = new Task<List<LimitInputModel>>(() =>
                    {
                        using (var stream = new MemoryStream())
                        {
                            model.xlsFile.CopyTo(stream);
                            return ExcelExport.inputData<LimitInputModel>(titles, stream);
                        }
                    });
                    task.Start();
                    var lst = await task;
                    if (lst.Count == 0) return ResultApi.error<bool>(false, "未读取到数据,请核对格式");
                    var powerStations = await this._db.tPowerStation.Where(x => x.dataState == 0).ToListAsync();
                    return await this.Create(lst.Select(x =>
                    {
                        var pId = powerStations.FirstOrDefault(k => k.powerStationNo == x.powerStationNo);
                        if (pId == null)
                            throw new Exception($"找不到{x.powerStationName},{x.powerStationNo}电站,导入失败");
                        if (x.limitValue <= 0)
                            throw new Exception($"{x.powerStationName},{x.powerStationNo}电站限购量小于或等于0,导入失败");

                        return new RequestLimitDataModel
                        {
                            powerStationId = pId.powerStationId,
                            date = x.limitDate.Date,
                            limitPowerValue = x.limitValue
                        };
                    }).ToList());
                    //return ResultApi.ok(true);
                }
            }
            return ResultApi.okOrError<bool>(false, false, "文件未上传");
        }

        ///// <summary>
        ///// 修改日限购量
        ///// </summary>
        //[HttpPut]
        //public async Task<ResultApi<bool>> Modify(tLimitPowerData model)
        //{
        //    await this.IsCheckPowerStation(model.limitPower_powerStationId_fk);
        //    await this._deviceDB.tLimitPowerData.Where(x => x.limitPowerId == model.limitPowerId).UpdateAsync(
        //        x=>new tLimitPowerData { 
        //            addTime = x.addTime,
        //            limitPowerValue= model.limitPowerValue,
        //        }
        //        );
        //    await this._deviceDB.SaveChangesAsync();
        //    return ResultApi.okOrError<bool>(true, true);
        //}



        /// <summary>
        /// 日限购量列表
        /// </summary>
        /// <param name="date">返回日期所在列表,不传返回所有日期的数据 </param>
        /// <param name="powerStationId">按电站返回,不传返回所有电站数据</param>
        /// <param name="model">分页</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<tLimitPowerData>>> LimitList([FromQuery] PageModel model, DateTime? date, decimal? powerStationId)
        {
            IQueryable<tLimitPowerData> q = this._deviceDB.tLimitPowerData;
            if (powerStationId.HasValue)
            {
                q = q.Where(x => x.limitPower_powerStationId_fk == powerStationId.Value);
            }
            if (date.HasValue)
            {
                q = q.Where(x => EF.Functions.DateDiffDay(x.addTime, date) == 0);

            }
            var result = await model.setPageAsync(q);
            return ResultApi.ok<List<tLimitPowerData>>(await result.Item2.ToListAsync(), result.Item1); ;
        }



        /// <summary>
        /// 删除限购量
        /// </summary>
        /// <param name="limitPowerId">限购ID</param>
        /// <returns></returns>
        [HttpDelete]
        public async Task<ResultApi<bool>> Delete(decimal limitPowerId)
        {
            await this._deviceDB.tLimitPowerData.DeleteByKeyAsync(limitPowerId);
            await this._deviceDB.SaveChangesAsync();
            return ResultApi.okOrError<bool>(true, true);
        }




        /// <summary>
        /// 生产信息日报
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<tableInfoToDay>>> TableInfoToDayAllPowerStationList(decimal? powerStationId, DateTime date)
        {
            if (powerStationId.HasValue)
                await this.IsCheckPowerStation(powerStationId.Value);
            IQueryable<tPowerStation> q = this._db.tPowerStation.Where(x => x.dataState == 0);
            if (powerStationId.HasValue)
            {
                q = q.Where(x => x.powerStationId == powerStationId.Value);
            }
            var powerStationLst = await q.ToListAsync();
            List<tableInfoToDay> lst = new List<tableInfoToDay>();
            foreach (var m in powerStationLst)
            {
                var prices = m.upPrice;

                tableInfoToDay model = new tableInfoToDay();
                model.powerStationName = m.powerStationName;
                model.powerStationId = m.powerStationId;
                model.date = date.Date;
                //产量和耗水量
                {
                    //日产量
                    model.dayPowerValue = await DataCache.PowerData.DayValue(date, m.powerStationId) / 10000;
                    //月产量
                    model.monthPowerValue = await DataCache.PowerData.MonthValue(date, m.powerStationId) / 10000;
                    model.beforeMonthPowerValue = await DataCache.PowerData.TongBiOfMonthy(date, m.powerStationId);
                    //年产量
                    model.yearPowerValue = await DataCache.PowerData.MonthValue(date, m.powerStationId) / 10000;
                    model.beforeYearPowerValue = await DataCache.PowerData.TongBiOfYear(date, m.powerStationId);
                    //耗水量
                    model.dayAverageWaterLevel = await DataCache.TurbineFlow.YearValue(date, m.powerStationId);
                }
                //销售量
                {
                    //日销售量
                    model.daySalePowerValue = await DataCache.SalesData.DayValue(date, m.powerStationId) / 10000;
                    //月销售电价
                    model.monthPowerPrice = prices.ToString("0.00");
                    //月销售量
                    model.monthSalePowerValue = await DataCache.SalesData.MonthValue(date, m.powerStationId) / 10000;
                    //月销售收入
                    model.monthSalePowerMoney = await DataCache.SalesMoney.DayValue(date, m.powerStationId);
                    //年销售量
                    model.yearSalePowerValue = await DataCache.SalesData.YearValue(date, m.powerStationId) / 10000;
                    //年销售量同比
                    model.beforeYearSalePowerValue = await DataCache.SalesData.TongBiOfYear(date, m.powerStationId);
                }
                //购电量
                {
                    model.dayBuyerPower = await DataCache.BuyPower.DayValue(date, m.powerStationId);
                }
                //日限制量
                {
                    model.dayLimitPower = (await DataCache.LimitPowerData.DayValue(date, m.powerStationId)) / 10000;
                    model.monthLimitPower = await DataCache.LimitPowerData.MonthValue(date, m.powerStationId) / 10000;
                    model.yearLimitPower = await DataCache.LimitPowerData.YearValue(date, m.powerStationId) / 10000;
                    model.beforeYearLimitPower = await DataCache.LimitPowerData.TongBiOfYear(date, m.powerStationId);
                }
                //来水量,算法未知
                {
                    //TODO 这里有无法计算的量
                    model.dayAverageAbandonment = 0;
                }
                //降水量
                {
                    model.dayRainfall = await DataCache.RainfallData.DayValue(date, m.powerStationId);
                    model.monthRainfall = await DataCache.RainfallData.MonthValue(date, m.powerStationId);
                }
                lst.Add(model);
            }


            return ResultApi.ok<List<tableInfoToDay>>(lst, 0);
        }

        /// <summary>
        /// 生产信息日报,导出
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
#if DEBUG
        [AllowAnonymous]
#endif
        public async Task<FileStreamResult> TableInfoToDayAllPowerStationDownload(decimal? powerStationId, DateTime date)
        {
            var m = await this.TableInfoToDayAllPowerStationList(powerStationId, date);
            var titles = await this._db.tExcelTitle.Where(x => x.excelType == 4).ToListAsync();
            if (titles.Count == 0) return new FileStreamResult(new MemoryStream(), new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            Task<Stream> task = Task.Run(async () =>
            {
                return ExcelExport.export(m.data, titles);
            });

            return new FileStreamResult(await task, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        }



        /// <summary>
        /// 生产水情日报管理
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<rainInfoToDay>>> RainInfoToDayList(decimal? powerStationId, DateTime date)
        {
            if (powerStationId.HasValue)
                await this.IsCheckPowerStation(powerStationId.Value);
            IQueryable<tPowerStation> q = this._db.tPowerStation.Where(x => x.dataState == 0);
            if (powerStationId.HasValue)
            {
                q = q.Where(x => x.powerStationId == powerStationId.Value);
            }
            var isNowYear = DateTime.Today.Year <= date.Year;
            var isToday = DateTime.Today <= date.Date;
            var powerStationLst = await q.ToListAsync();
            List<rainInfoToDay> lst = new List<rainInfoToDay>();
            foreach (var m in powerStationLst)
            {
                rainInfoToDay model = new rainInfoToDay();
                model.powerStationName = m.powerStationName;
                model.date = date.Date;
                //8时上游
                {
                    model.upstreamWaterLevel = 0;
                    model.downstreamWaterLevel = 0;
                    model.beforeUpstreamWaterLevel = 0;
                    model.beforeUpstreamWaterLevel = 0;
                }
                lst.Add(model);
            }
            return ResultApi.ok<List<rainInfoToDay>>(lst, lst.Count());
        }

        /// <summary>
        /// 生产水情日报管理,导出
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
#if DEBUG
        [AllowAnonymous]
#endif
        public async Task<FileStreamResult> RainInfoToDayAllPowerStationDownload(decimal? powerStationId, DateTime date)
        {
            var m = await this.RainInfoToDayList(powerStationId, date);
            var titles = await this._db.tExcelTitle.Where(x => x.excelType == 5).ToListAsync();
            if (titles.Count == 0) return new FileStreamResult(new MemoryStream(), new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            Task<Stream> task = Task.Run(async () =>
            {
                return ExcelExport.export(m.data, titles);
            });
            return new FileStreamResult(await task, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        }





        /// <summary>
        /// 生产信息月报
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<tableInfoToMonth>>> TablInfoToMonthAllPowerStationList(long? powerStationId, DateTime date)
        {
            if (powerStationId.HasValue)
                await this.IsCheckPowerStation(powerStationId.Value);
            else
                powerStationId = 0;

            List<tableInfoToMonth> lst = new List<tableInfoToMonth>();

            for (DateTime i = new DateTime(date.Year, date.Month, 01); i.IsSameMonth(date); i = i.AddDays(1))
            {
                var isToday = DateTime.Today <= i;
                tableInfoToMonth model = new tableInfoToMonth();
                model.date = $"{i:dd}";
                //发电量
                {
                    model.dayPowerValue = (await DataCache.PowerData.DayValue(i, powerStationId.Value)) / 10000;
                }
                //日上网电量
                {
                    model.daySalePowerValue = (await DataCache.SalesData.DayValue(i, powerStationId.Value)) / 10000;
                }
                //日厂用电量
                {
                    model.dayUsePowerValue = (await DataCache.FactoryUsePower.DayValue(i, powerStationId.Value)) / 10000;
                }
                //日购电量
                {
                    model.dayBuyPowerValue = (await DataCache.BuyPower.DayValue(i, powerStationId.Value)) / 10000;
                }
                //运行容量
                {
                    model.dayOperatingCapacityValue = (await DataCache.RunPower.DayValue(i, powerStationId.Value));
                }
                //入库总水量
                {

                }


                lst.Add(model);
            }


            return ResultApi.ok<List<tableInfoToMonth>>(lst, 0);
        }

        /// <summary>
        /// 生产信息月报,导出
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
#if DEBUG
        [AllowAnonymous]
#endif
        public async Task<FileStreamResult> TableInfoToMonthAllPowerStationDownload(long? powerStationId, DateTime date)
        {
            var m = await this.TablInfoToMonthAllPowerStationList(powerStationId, date);
            var titles = await this._db.tExcelTitle.Where(x => x.excelType == 6).ToListAsync();
            if (titles.Count == 0) return new FileStreamResult(new MemoryStream(), new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            Task<Stream> task = Task.Run(async () =>
            {
                return ExcelExport.export(m.data, titles);
            });

            return new FileStreamResult(await task, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        }

        /// <summary>
        /// 重新统计电站书局
        /// </summary>
        /// <param name="powerStationId">电站Id</param>
        /// <param name="date">需要计算的日期</param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ResultApi<bool>> recalculate(long powerStationId, DateTime date)
        {
            var d = date.Date;
            var nextDay = d.AddDays(1);
            var station = this._db.tPowerStation.FirstOrDefault(x => x.powerStationId == powerStationId);
            if (station == null)
                return ResultApi.error(false, "未找到电站");

            double _Interval = 30;
            while (d < nextDay)
            {
                //todo
                await Notication.AppCode.StatisticsUtils.doCalculatePower(d, station);
                //每30分钟统计
                d = d.AddMinutes(_Interval);
            }
            return ResultApi.ok(true);
        }
        /// <summary>
        /// 生产信息年报
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResultApi<List<tableInfoToYear>>> TablInfoToYearAllPowerStationList(long? powerStationId, DateTime date)
        {
            if (powerStationId.HasValue)
                await this.IsCheckPowerStation(powerStationId.Value);
            else
            {
                powerStationId = 0;
            }

            /* List<tableInfoToYear> lst = new List<tableInfoToYear>();
             bool isToday = false;
             for (DateTime i = new DateTime(date.Year, 01, 01); i.IsSameYear(date); i = i.AddMonths(1))
             {
                 isToday = !isToday && i.IsSameMonth(DateTime.Today);
                 tableInfoToYear model = new tableInfoToYear();
                 model.date = $"{i:MM}";

                 //月发电量
                 {
                     model.monthPowerValue = (await DataCache.PowerData.MonthValue(i,powerStationId.Value))/10000;
                 }
                 //月上网电量
                 {
                     model.monthSalePowerValue = await DataCache.SalesData.MonthValue(i, powerStationId.Value) / 10000;
                 }
                 //月厂用电量
                 {
                     model.monthUsePowerValue = await DataCache.FactoryUsePower.MonthValue(i, powerStationId.Value) / 10000;
                 }
                 //月购电量
                 {
                     model.monthBuyPowerValue = await DataCache.BuyPower.MonthValue(i, powerStationId.Value) / 10000;
                 }
                 //月运行容量
                 {
                     model.monthOperatingCapacityValue = await DataCache.RunPower.MonthValue(i, powerStationId.Value);
                 }
                 //入库总水量
                 {

                 }
                 lst.Add(model);
             }*/

            List<tableInfoToYear> datalist = new List<tableInfoToYear>();
            if (powerStationId != 0)
            {
                for (int i = 1; i < 13; i++)
                {
                    var dataOne = this._deviceDB.vStatisticsData.Where(x => x.statisticsDataDate.Year == date.Year && x.statisticsDataDate.Month == i && x.statisticsStation_powerStationId_fk == powerStationId);
                    tableInfoToYear dataSet;
                    if (dataOne.Count() != 0)
                    {
                        dataSet = dataOne.GroupBy(x => new { x.statisticsDataDate.Year, x.statisticsDataDate.Month })
                         .Select(group => new tableInfoToYear
                         {
                             date = new DateTime(group.Key.Year, group.Key.Month, 1, 0, 0, 0).ToString("yyyy-MM"),
                             monthPowerValue = group.Sum(data => data.power) / 10000,
                             monthSalePowerValue = group.Sum(data => data.salePower) / 10000,
                             monthUsePowerValue = group.Sum(data => data.factoryUsePower) / 10000,
                             monthBuyPowerValue = group.Sum(data => data.buyPower) / 10000,
                             monthOperatingCapacityValue = group.Sum(data => data.runningCapacity)
                         }).ToList().FirstOrDefault();
                    }
                    else
                    {
                        dataSet = new tableInfoToYear()
                        {
                            date = new DateTime(date.Year, i, 1, 0, 0, 0).ToString("yyyy-MM"),
                            monthPowerValue = 0,
                            monthSalePowerValue = 0,
                            monthUsePowerValue = 0,
                            monthBuyPowerValue = 0,
                            monthOperatingCapacityValue = 0
                        };
                    }
                    datalist.Add(dataSet);
                }
            }
            else
            {
                for (int i = 1; i < 13; i++)
                {
                    var dataOne = this._deviceDB.vStatisticsData.Where(x => x.statisticsDataDate.Year == date.Year && x.statisticsDataDate.Month == i);
                    tableInfoToYear dataSet;
                    if (dataOne.Count() != 0)
                    {
                        dataSet = dataOne.GroupBy(x => new { x.statisticsDataDate.Year, x.statisticsDataDate.Month })
                         .Select(group => new tableInfoToYear
                         {
                             date = new DateTime(group.Key.Year, group.Key.Month, 1, 0, 0, 0).ToString("yyyy-MM"),
                             monthPowerValue = group.Sum(data => data.power) / 10000,
                             monthSalePowerValue = group.Sum(data => data.salePower) / 10000,
                             monthUsePowerValue = group.Sum(data => data.factoryUsePower) / 10000,
                             monthBuyPowerValue = group.Sum(data => data.buyPower) / 10000,
                             monthOperatingCapacityValue = group.Sum(data => data.runningCapacity)
                         }).ToList().FirstOrDefault();
                    }
                    else
                    {
                        dataSet = new tableInfoToYear()
                        {
                            date = new DateTime(date.Year, i, 1, 0, 0, 0).ToString("yyyy-MM"),
                            monthPowerValue = 0,
                            monthSalePowerValue = 0,
                            monthUsePowerValue = 0,
                            monthBuyPowerValue = 0,
                            monthOperatingCapacityValue = 0
                        };
                    }
                    datalist.Add(dataSet);
                }
            }


            return ResultApi.ok<List<tableInfoToYear>>(datalist, 0);
        }

        /// <summary>
        /// 生产信息年报,导出
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="powerStationId">电站ID,不传就查所有电站</param>
        /// <returns></returns>
        [HttpGet]
#if DEBUG
        [AllowAnonymous]
#endif
        public async Task<FileStreamResult> TableInfoToYearAllPowerStationDownload(long? powerStationId, DateTime date)
        {
            var m = await this.TablInfoToYearAllPowerStationList(powerStationId, date);
            var titles = await this._db.tExcelTitle.Where(x => x.excelType == 7).ToListAsync();
            if (titles.Count == 0) return new FileStreamResult(new MemoryStream(), new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
            Task<Stream> task = Task.Run(async () =>
            {
                return ExcelExport.export(m.data, titles);
            });

            return new FileStreamResult(await task, new MediaTypeHeaderValue("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
        }
    }
}
